﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.InteropServices;
using PSAMMatrixCloud.Model;
using System.Collections.Concurrent;
using DotNetty.Transport.Channels;
using PSAMMatrixCloud.Model.PSAMMatrix;

namespace PSAMMatrixCloud.TransferSecret.PSAMMatrix
{
    public class PSAMSocket
    {
        private static object ObjLock = new object();
        /// <summary>
        /// 队列数据缓存块
        /// </summary>
        private static ConcurrentDictionary<string, Queue<LaneDataPackage>> LaneDataPackageRequest = new ConcurrentDictionary<string, Queue<LaneDataPackage>>();

        private readonly static byte[] ProtocolHead = { 0x55, 0xAA };

        /// <summary>
        /// 数据包入队
        /// </summary>
        /// <param name="MatrixNo"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static bool VehickeInfoEnqueue(string MatrixNo, LaneDataPackage Data) 
        {
            bool Result = false;
            MatrixNo = MatrixNo + "@";
            var MatrixCollect = LaneDataPackageRequest.Keys.Where(p => p.StartsWith(MatrixNo));
            if (MatrixCollect != null && MatrixCollect.Count() > 0)
            {
                if (Data.CommandType == DeviceCommandTypeAsk.VehicleInfo)
                {
                    var MatixIdleChannel = LaneDataPackageRequest.Where(p => MatrixCollect.Contains(p.Key)).Select(p => new { IdleNum = p.Value.Count(), MatrixChannelNo = p.Key }).Where(p => p.IdleNum == 0).OrderBy(p => p.MatrixChannelNo).FirstOrDefault();
                    if (MatixIdleChannel != null)
                    {
                        if (LaneDataPackageRequest.ContainsKey(MatixIdleChannel.MatrixChannelNo))
                        {
                            var Matrix = LaneDataPackageRequest[MatixIdleChannel.MatrixChannelNo];
                            if (Matrix != null)
                            {
                                Matrix.Enqueue(Data);
                            }
                            else
                            {
                                var queue = new Queue<LaneDataPackage>();
                                queue.Enqueue(Data);
                                LaneDataPackageRequest[MatixIdleChannel.MatrixChannelNo] = queue;
                            }
                        }
                        else
                        {
                            var queue = new Queue<LaneDataPackage>();
                            queue.Enqueue(Data);
                            LaneDataPackageRequest[MatixIdleChannel.MatrixChannelNo] = queue;
                        }
                    }

                }
            }
            return Result;
        }

        

        /// <summary>
        /// 数据包入队
        /// </summary>
        /// <param name="MatrixChannelNo"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static bool MacInfoEnqueue(string MatrixChannelNo, LaneDataPackage Data)
        {
            bool Result = true;
            var MatrixCollect = LaneDataPackageRequest.Keys.Where(p => p.Contains(MatrixChannelNo));
            if (MatrixCollect != null && MatrixCollect.Count() > 0)
            {
                if (Data.CommandType != DeviceCommandTypeAsk.VehicleInfo)
                {
                    if (LaneDataPackageRequest.ContainsKey(MatrixChannelNo))
                    {
                        var Matrix = LaneDataPackageRequest[MatrixChannelNo];
                        if (Matrix != null)
                        {
                            Matrix.Enqueue(Data);
                        }
                        
                        else
                        {
                            var queue = new Queue<LaneDataPackage>();
                            queue.Enqueue(Data);
                            LaneDataPackageRequest[MatrixChannelNo] = queue;
                        }
                    }
                    else
                    {
                        var queue = new Queue<LaneDataPackage>();
                        queue.Enqueue(Data);
                        LaneDataPackageRequest[MatrixChannelNo] = queue;
                    }
                }
            }
            return Result;
        }

        /// <summary>
        /// 创建后台线程
        /// </summary>
        /// <param name="Matrix"></param>
        public static void Start()
        {
            List<PSAMMatrixCloud.Model.psam_matrixModel> Matrix = new PSAMMatrixCloud.BLL.psam_matrix().GetModelList(" status=1 ");
            foreach (var entity in Matrix)
            {
                
                for (int Index = 0; Index < entity.maxconnectnum; Index++)
                {
                    PSAMChannelManage pSAMChannelManage = PSAMChannelManage.AutoCopy(entity);
                    pSAMChannelManage.Channel = Index;
                    ThreadPool.QueueUserWorkItem(Run, pSAMChannelManage);
                    LaneDataPackageRequest[entity.matrixno +"@"+ Index]= new Queue<LaneDataPackage>();
                }
            }
            Common.LogHelper.Info("启动与psam加密盒子通讯服务成功");
        }

        

        #region 通讯服务
        /// <summary>
        /// 通讯服务
        /// </summary>
        /// <param name="Obj"></param>
        private static void Run(object Obj)
        {
            PSAMMatrixCloud.Model.PSAMChannelManage Entity = (PSAMMatrixCloud.Model.PSAMChannelManage)Obj;
            string ChaneelName = Entity.matrixno + "@" + Entity.Channel;
            Common.LogHelper.Info($"通道号:【{ChaneelName}】启动");
           
            //缓存
            byte[] pBuffer = new byte[2048];
            Socket Client = null;
            while (true)
            {
                Ping p = new Ping();
                try
                {
                    //ping服务端
                    if (p.Send(Entity.matrixip, 10000000).Status == IPStatus.Success)
                    {
                        Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + " 网络正常");
                        Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        Client.Connect(Entity.matrixip, int.Parse(Entity.matrixport));
                        #region 连接状态
                        if (!Client.Connected)
                        {
                            Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "  连接失败!");
                            Client = null;
                            //延时
                            Thread.Sleep(10);
                            continue;
                        }

                        SessionInfo session = new SessionInfo()
                        {
                            PSAMIdleCount = 1,
                            SessionID = Guid.NewGuid().ToString().Replace("-", ""),
                            PSAMMatrixNo = Entity.matrixno,
                            CreateTime = DateTime.Now
                        };
                        PSAMChannelManager.Add(Entity.matrixno,session);
                        LaneDataPackage LaneData = null;
                        while (true)
                        {
                            try
                            {
                                Queue<LaneDataPackage> Matrix = null;
                               
                                if (LaneDataPackageRequest.ContainsKey(ChaneelName))
                                {
                                    Matrix = LaneDataPackageRequest[ChaneelName];
                                    
                                    if (Matrix == null)
                                    {
                                        Thread.Sleep(100);
                                        Common.LogHelper.Info("无效PSAM加密盒子编号：" + Entity.matrixno);
                                        continue;
                                    }
                                    else
                                    {
                                        if (Matrix.Count > 0)
                                        {
                                            Common.LogHelper.Server($"通道号:【{ChaneelName}】  数据包内容：{ Newtonsoft.Json.JsonConvert.SerializeObject(Matrix)}");
                                        }
                                    }
                                }
                               

                                //检测是否可以写
                                if (Client.Poll(10000, SelectMode.SelectWrite))
                                {
                                    if (Matrix != null)
                                    {
                                        while (Matrix.Count>0)
                                        {
                                            LaneData = Matrix.Dequeue();
                                            if (LaneData != null)
                                            {
                                                if ((DateTime.Now - LaneData.RecvTime).Seconds < 60)
                                                {
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                        if (LaneData != null && !LaneData.IsDownLoad)
                                        {
                                            Common.LogHelper.Info($"通道号:【{ChaneelName}】  数据包内容：{ Newtonsoft.Json.JsonConvert.SerializeObject(LaneData)}");
                                            DateTime CurrentDataTime = DateTime.Now;
                                            CustomProtocolPackage(Client, ref CurrentDataTime, Entity, 2, LaneData);
                                            LaneData.IsDownLoad = true;
                                        }
                                    }
                                }
                                else
                                {
                                    if(Matrix!=null && Matrix.Count>0)
                                    {
                                        break;
                                    }
                                }
                                //检测是否可以读
                                if (Client.Poll(100000, SelectMode.SelectRead))
                                {
                                    Client.ReceiveTimeout =300000;

                                    //接收数据包
                                    int Len = Client.Receive(pBuffer);
                                    if (Len == 0)
                                        break;
                                    Common.LogHelper.Info("PSAM加密盒子响应数据包内容：" + Common.Check.ByteArrayToHexString(pBuffer, 0, Len));
                                    byte[] ReciveBuffer = new byte[Len];
                                    Array.ConstrainedCopy(pBuffer, 0, ReciveBuffer, 0, Len);
                                    if (LaneData == null)
                                    {
                                        Common.LogHelper.Debug("PSAM加密盒子响应数据超时，数据内容：" + Common.Check.ByteArrayToHexString(ReciveBuffer));
                                    }
                                    ProcessingPackage(Entity, ReciveBuffer, Len, LaneData);
                                }
                                else
                                {
                                    //break;
                                }
  
                            }
                            catch (Exception ex)
                            {
                                Common.LogHelper.Error("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity), ex);
                                break;
                            }
                        }
                        #endregion
                        if (Client != null)
                        {
                            if (Client.Connected)
                                Client.Disconnect(true);
                            Client.Close();
                            Client = null;
                        }
                    }
                    else
                    {
                        Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "网络异常，可能网线已拔或者设备关机!");
                    }
                }
                catch (Exception ex)
                {
                    Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity), ex);
                    if (Client != null)
                    {
                        if (Client.Connected)
                            Client.Disconnect(true);
                        Client.Close();
                        Client = null;
                    }
                }
                finally
                {
                    p.Dispose();
                }
            }
        }
        #endregion


        #region 处理包
        /// <summary>
        /// 处理包
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="pBuffer"></param>
        /// <param name="laneData"></param>
        /// <returns></returns>
        private static void ProcessingPackage(PSAMMatrixCloud.Model.PSAMChannelManage entity, byte[] pBuffer, int length, LaneDataPackage laneData)
        {
            try
            {
                byte[] headBytes = new byte[2];
                byte[] lengthBytes = new byte[2]; 
                byte[] CommandBytes = new byte[1];
                int Index = 0;
                while (Index+7 < length)
                {
                    try
                    {
                        Array.ConstrainedCopy(pBuffer, Index, headBytes,0 , 2);

                        if (Enumerable.SequenceEqual(headBytes,ProtocolHead))
                        {
                            if (Index + 6 < length)
                            {
                                Array.ConstrainedCopy(pBuffer, Index + 3, lengthBytes, 0, 2);
                                Array.ConstrainedCopy(pBuffer, Index + 4, CommandBytes,0 , 1);
                                if(BitConverter.IsLittleEndian)
                                {
                                    Array.Reverse(lengthBytes);
                                }
                                //数据长度
                                short datalen = BitConverter.ToInt16(lengthBytes);
                                if (Index + datalen + 6 <= length)
                                {
                                    byte[] DataPackageBuffer = new byte[datalen + 7];
                                    Array.ConstrainedCopy(pBuffer, Index, DataPackageBuffer, 0, datalen + 7);
                                    Message msg = new Message(DataPackageBuffer);
                                    AnalyseControlerData(entity, laneData, msg);

                                    Index = Index + datalen + 7;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Common.LogHelper.Error($"处理数据包:{Common.Check.ByteArrayToHexString(pBuffer)} 过程异常", ex);
                    }
                    Index++;
                }
            }
            catch (Exception ex)
            {
                Common.LogHelper.Error($"处理数据包:{Common.Check.ByteArrayToHexString(pBuffer)} 过程异常", ex);
            }

        }
        #endregion

        #region 解析返回数据
        /// <summary>
        ///  解析返回数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="laneData"></param>
        /// <param name="message"></param>
        public static void AnalyseControlerData(PSAMChannelManage entity,LaneDataPackage laneData,Message message)
        {
            switch ((DeviceCommandTypeReply)message.CommandType)
            {
                case DeviceCommandTypeReply.TransparentTransmission://透传
                    Common.LogHelper.Info("【指令类型：透传】 PSAM加密盒子响应数据：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    AnalyseTransparentTransmission(entity,laneData, message);
                    break;
                case DeviceCommandTypeReply.HeartBeat://心跳
                    Common.LogHelper.Info("【指令类型：心跳】 PSAM加密盒子响应数据：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    AnalyseHeartBeat(entity, message);
                    break;
                default:
                    Common.LogHelper.Info("【指令类型：未知指令】 PSAM加密盒子响应数据：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    break;
            }
        }
        #endregion

        #region 解析透传指令
        /// <summary>
        /// 解析透传指令
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="laneData"></param>
        /// <param name="data"></param>
        private static void AnalyseTransparentTransmission(PSAMChannelManage entity, LaneDataPackage laneData,Message data)
        {
            var session = PSAMChannelManager.GetChannel(entity.matrixno);
            IChannel channel = null;
            if (laneData != null)
            {
                channel = LaneMutual.LaneChannelManager.GetChannel(laneData.DeviveID);
            }
            LaneMutual.Message message = null;
            session.LastAccessTime = DateTime.Now;
            MessagePsam psam = new MessagePsam(data.Body);
            byte[] deviceid = new byte[4];
            Array.ConstrainedCopy(BitConverter.GetBytes(int.Parse(laneData.DeviveID)), 0, deviceid, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(deviceid); // 转换为 大端模式               
            }
            LaneMutual.SessionInfo lanesession;
            switch ( laneData.CommandType)
            {
                case DeviceCommandTypeAsk.VehicleInfo:
                    message = new LaneMutual.Message((int)ServerCommandTypeReply.VehicleInfo, data.MessageID);
                    Array.ConstrainedCopy(deviceid, 0, message.Body, 0, 4);
                    if (psam.STATUS == 0x00)
                    {
                        switch (psam.APDU_LIST.Length)
                        {
                            case 0x04:

                                if (Enumerable.SequenceEqual(psam.APDU_LIST,new Byte[]{ 0x01,0x02,0x90,0x00}))
                                {
                                    lanesession = LaneMutual.LaneChannelManager.GetSessionInfo(channel);

                                    lanesession.PSAMMatrixNo = entity.matrixno;
                                    lanesession.PSAMMatrixChannelNo = entity.matrixno+"@"+ entity.Channel.ToString();
                                    lanesession.PSAMNo = BitConverter.ToString(psam.PHY_ID).Replace("-","");
                                    lanesession.TerminalNo = BitConverter.ToString(psam.TID).Replace("-", "");
                                    if (laneData.TerminalNo == "FFFFFFFFFFFF")
                                    {
                                        Common.LogHelper.Info("PSAM加密盒子初始化成功：" + BitConverter.ToString(psam.APDU_LIST) + " entity:" + Newtonsoft.Json.JsonConvert.SerializeObject(entity));
                                    }
                                    else
                                    {
                                        Common.LogHelper.Error("PSAM加密盒子步骤错误：" + BitConverter.ToString(psam.APDU_LIST) + " entity:" + Newtonsoft.Json.JsonConvert.SerializeObject(entity));
                                    }
                                }
                                else
                                {
                                    Common.LogHelper.Error("PSAM加密盒子初始化错误：" + BitConverter.ToString(psam.APDU_LIST) + " entity:" + Newtonsoft.Json.JsonConvert.SerializeObject(entity));
                                    Array.ConstrainedCopy(psam.APDU_LIST, 0, message.Body, 6, 2);
                                   
                                    if(laneData==null)
                                    {
                                        channel = LaneMutual.LaneChannelManager.GetChannel(entity.matrixno,"FFFF","FFFFFFFFFFFF");
                                    }

                                    if (channel != null)
                                    {
                                        Common.LogHelper.Info("云端向车道响应数据[PSAM卡初始化]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));

                                        channel.WriteAndFlushAsync(message);
                                    }
                                }
                                break;

                            case 0x4C:
                                message.Body[5] = psam.APDU_LIST[74];
                                message.Body[4] = psam.APDU_LIST[75];
                                Array.ConstrainedCopy(psam.APDU_LIST, 11, message.Body, 6, 16);
                                var plateno = new byte[12];
                                Array.ConstrainedCopy(psam.APDU_LIST, 11, plateno, 0, 12);

                                Array.ConstrainedCopy(psam.TID, 0, message.Body, 22, 6);
                                if (laneData == null)
                                {
                                    channel = LaneMutual.LaneChannelManager.GetChannel(entity.matrixno, BitConverter.ToString(psam.PHY_ID).Replace("-", ""), BitConverter.ToString(psam.TID).Replace("-", ""));
                                }
                                if (channel != null)
                                {
                                    Common.LogHelper.Info("云端向车道响应数据[车辆信息解密]：" + Common.Check.ByteArrayToHexString(message.ToBytes())+"  【车牌号码】:"+ Encoding.GetEncoding("GBK").GetString(plateno));
                                    channel.WriteAndFlushAsync(message);
                                }
                                break;
                            default:
                                byte[] response_code= BitConverter.GetBytes(psam.APDU_LIST.Length);
                                Array.ConstrainedCopy(response_code, 0, message.Body, 6, 2);
                                if (channel != null)
                                {
                                    Common.LogHelper.Error("云端向车道响应数据[车辆信息]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                                    channel.WriteAndFlushAsync(message);
                                }
                                break;
                        }
                    }
                    else
                    {
                        message.Body[5] = psam.STATUS;
                        if (channel != null)
                        {
                            Common.LogHelper.Error("云端向车道响应数据[车辆信息]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                            channel.WriteAndFlushAsync(message);
                        }
                    }
                    break;
                case DeviceCommandTypeAsk.MAC1:
                    message = new LaneMutual.Message((int)ServerCommandTypeReply.MAC1, data.MessageID);
                    Array.ConstrainedCopy(deviceid, 0, message.Body, 0, 4);
                    if (laneData == null)
                    {
                        channel = LaneMutual.LaneChannelManager.GetChannel(entity.matrixno, BitConverter.ToString(psam.PHY_ID).Replace("-", ""), BitConverter.ToString(psam.TID).Replace("-", ""));
                    }
                    if (psam.STATUS == 0x00)
                    {
                        switch (psam.APDU_LIST.Length)
                        {
                            case 0x0C:
                                message.Body[5] = psam.APDU_LIST[10];
                                message.Body[4] = psam.APDU_LIST[11];
                                Array.ConstrainedCopy(laneData.LaneData, 10, message.Body, 6, 4);
                                Array.ConstrainedCopy(psam.TID, 0, message.Body, 10, 6);
                                Array.ConstrainedCopy(laneData.LaneData, 20, message.Body, 16, 4);
                                Array.ConstrainedCopy(laneData.LaneData, 25, message.Body, 20, 7);
                                Array.ConstrainedCopy(laneData.LaneData, 24, message.Body, 27, 1);
                                Array.ConstrainedCopy(psam.APDU_LIST, 2, message.Body, 28, 8);
                                if (channel != null)
                                {
                                    Common.LogHelper.Info("云端向车道响应数据[计算MAC1]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                                    channel.WriteAndFlushAsync(message);
                                }
                                break;
                            default:
                                byte[] response_code = BitConverter.GetBytes(psam.APDU_LIST.Length);
                                Array.ConstrainedCopy(response_code, 0, message.Body, 6, 2);
                                if (channel != null)
                                {
                                    Common.LogHelper.Error("云端向车道响应数据[计算MAC1]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                                    channel.WriteAndFlushAsync(message);
                                }
                                break;
                        }
                    }
                    else
                    {
                        message.Body[5] = psam.STATUS;
                        if (channel != null)
                        {
                            Common.LogHelper.Error("云端向车道响应数据[计算MAC1]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                            channel.WriteAndFlushAsync(message);
                        }
                    }
                    break;
                case DeviceCommandTypeAsk.MAC2:
                    message = new LaneMutual.Message((int)ServerCommandTypeReply.MAC2, data.MessageID);
                    Array.ConstrainedCopy(deviceid, 0, message.Body, 0, 4);
                    if (laneData == null)
                    {
                        channel = LaneMutual.LaneChannelManager.GetChannel(entity.matrixno, BitConverter.ToString(psam.PHY_ID).Replace("-", ""), BitConverter.ToString(psam.TID).Replace("-", ""));
                    }
                    switch (psam.APDU_LIST.Length)
                    {
                        case 0x04:
                            message.Body[5] = psam.APDU_LIST[2];
                            message.Body[4] = psam.APDU_LIST[3];
                            Array.ConstrainedCopy(laneData.LaneData, 10, message.Body, 6, 4);
                            Array.ConstrainedCopy(psam.TID, 0, message.Body, 10, 6);

                            if (channel != null)
                            {
                                Common.LogHelper.Info("云端向车道响应数据[验证MAC2]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                                channel.WriteAndFlushAsync(message);
                            }
                            break;
                        default:
                            byte[] response_code = BitConverter.GetBytes(psam.APDU_LIST.Length);
                            Array.ConstrainedCopy(response_code, 0, message.Body, 6, 2);
                            if (channel != null)
                            {
                                Common.LogHelper.Error("云端向车道响应数据[验证MAC2]：" + Common.Check.ByteArrayToHexString(message.ToBytes()));
                                channel.WriteAndFlushAsync(message);
                            }
                            break;
                    }
                    break;
            }
        }
        #endregion

        #region 解析心跳包数据
        /// <summary>
        /// 解析心跳包数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="data"></param>
        private static void  AnalyseHeartBeat(PSAMChannelManage entity,Message data)
        {
           SessionInfo session= PSAMChannelManager.GetChannel(entity.matrixno);
            if(session!=null)
            {
                session.PSAMIdleCount= BitConverter.ToUInt32(data.Body);
                session.LastAccessTime = DateTime.Now;
            }
        }

        #endregion

        #region 发送心跳数据包
        /// <summary>
        /// 发送心跳数据包
        /// </summary>
        /// <param name="Client"></param>
        /// <param name="HistoryDate"></param>
        /// <param name="Entity"></param>
        /// <param name="TimeOut"></param>
        /// <returns></returns>
        public static bool CustomHeartBeat(Socket Client, ref DateTime HistoryDate, object Entity, int TimeOut)
        {
            bool Result = true;
            Client.SendTimeout = 200;
            if (Client.Send(Encoding.ASCII.GetBytes("!!OK^^")) != "!!OK^^".Length)
            {
                if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                {
                    HistoryDate = DateTime.Now;
                    Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送心跳包失败");
                }
                Result = false;
            }
            else
            {
                if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                {
                    HistoryDate = DateTime.Now;
                    Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送心跳包成功");
                }
            }
            return Result;
        }
        #endregion

        #region 发送数据包
        /// <summary>
        /// 发送数据包
        /// </summary>
        /// <param name="Client"></param>
        /// <param name="HistoryDate"></param>
        /// <param name="Entity"></param>
        /// <param name="TimeOut"></param>
        /// <param name="LanePackage"></param>
        /// <returns></returns>
        public static bool CustomProtocolPackage(Socket Client, ref DateTime HistoryDate, object Entity, int TimeOut, LaneDataPackage LanePackage)
        {
            //缓存大小
            int Size = 2048;

            //缓存
            byte[] pBuffer = new byte[Size];
            bool Result = true;
            Client.SendTimeout = 200;
            Message message = null;
            var channel = LaneMutual.LaneChannelManager.GetChannel(LanePackage.DeviveID);
            var lanesession = LaneMutual.LaneChannelManager.GetSessionInfo(channel);
            byte[] COSHead  ;

            switch (LanePackage.CommandType)
            {
                case DeviceCommandTypeAsk.VehicleInfo:
                    //第一步初始化PSAM
                    message = new Message((int)LanePackage.CommandType, LanePackage.LaneData[2], true);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(LanePackage.PSAMNo),0, message.Body,0,2);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(LanePackage.TerminalNo), 0, message.Body, 2, 6);
                    message.Body[8] = 0x01;//是否下条指令(0x00 表示没有下一条指令；0x01表示有下一条指令)
                    message.Body[9] = 0x01;//指令数
                    message.Body[10] = 0x15;//指令数据长度
                    COSHead = new byte[5] { 0x80, 0x1a, 0x59, 0x03, 0x10 };
                    Array.ConstrainedCopy(COSHead, 0, message.Body, 11, 5);
                    Array.ConstrainedCopy(LanePackage.LaneData, 10, message.Body, 16, message.Body.Length - 16);

                    if (Client.Send(message.ToBytes()) != message.ToBytes().Length)
                    {
                        if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                        {
                            HistoryDate = DateTime.Now;
                            Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送初始化PSAM请求数据帧失败，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                        }
                        Result = false;
                    }
                    else
                    {
                        HistoryDate = DateTime.Now;
                        Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送初始化PSAM请求数据帧成功，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    }
                    //检测是否可以读
                    if (Client.Poll(100000, SelectMode.SelectRead))
                    {
                        Client.ReceiveTimeout = 500;

                        //接收数据包
                        int Len = Client.Receive(pBuffer);
                        if (Len == 0)
                            break;
                        Common.LogHelper.Info("PSAM加密盒子响应数据帧内容：" + Common.Check.ByteArrayToHexString(pBuffer, 0, Len));
                        byte[] ReciveBuffer = new byte[Len];
                        Array.ConstrainedCopy(pBuffer, 0, ReciveBuffer, 0, Len);
                        ProcessingPackage((PSAMChannelManage)Entity, ReciveBuffer, Len, LanePackage);
                    }
                    else
                    {
                        return false;
                    }
                    
                    //第二步解密车辆信息
                    message = new Message((int)LanePackage.CommandType, LanePackage.LaneData[2], false);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.PSAMNo), 0, message.Body, 0, 2);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.TerminalNo), 0, message.Body, 2, 6);
                    message.Body[8] = 0x01;//是否下条指令(0x00 表示没有下一条指令；0x01表示有下一条指令)
                    message.Body[9] = 0x01;//指令数
                    message.Body[10] = 0x4d;//指令数据长度
                    COSHead = new byte[5] { 0x80, 0xfa, 0x80 ,0x00,0x48 };
                    Array.ConstrainedCopy(COSHead, 0, message.Body, 11, 5);
                    Array.ConstrainedCopy(LanePackage.LaneData, 26, message.Body, 16, message.Body.Length - 16);
                    if (Client.Send(message.ToBytes()) != message.ToBytes().Length)
                    {
                        if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                        {
                            HistoryDate = DateTime.Now;
                            Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送车辆信息解密请求失败，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                        }
                        Result = false;
                    }
                    else
                    {
                        HistoryDate = DateTime.Now;
                        Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送车辆信息解密请求成功，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    }
                    break;
                case DeviceCommandTypeAsk.MAC1:
                    message = new Message((int)LanePackage.CommandType, LanePackage.LaneData[2], true);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.PSAMNo), 0, message.Body, 0, 2);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.TerminalNo), 0, message.Body, 2, 6);
                    message.Body[8] = 0x01;//是否下条指令(0x00 表示没有下一条指令；0x01表示有下一条指令)
                    message.Body[9] = 0x01;//指令数
                    message.Body[10] = 0x29;//指令数据长度
                    COSHead = new byte[5] { 0x80, 0x70, 0x00, 0x00, 0x24 };
                    Array.ConstrainedCopy(COSHead, 0, message.Body, 11, 5);
                    Array.ConstrainedCopy(LanePackage.LaneData, 14, message.Body, 16, message.Body.Length - 16);

                    if (Client.Send(message.ToBytes()) != message.ToBytes().Length)
                    {
                        if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                        {
                            HistoryDate = DateTime.Now;
                            Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送计算MAC1请求失败，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                        }
                        Result = false;
                    }
                    else
                    {
                        HistoryDate = DateTime.Now;
                        Common.LogHelper.Info("向PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送计算MAC1请求成功，请求数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    }
                    break;
                case DeviceCommandTypeAsk.MAC2:
                    message = new Message((int)LanePackage.CommandType, LanePackage.LaneData[2], true);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.PSAMNo), 0, message.Body, 0, 2);
                    Array.ConstrainedCopy(Common.Check.HexStringToByteArray(lanesession.TerminalNo), 0, message.Body, 2, 6);
                    message.Body[8] = 0x00;//是否下条指令(0x00 表示没有下一条指令；0x01表示有下一条指令)
                    message.Body[9] = 0x01;//指令数
                    message.Body[10] = 0x09;//指令数据长度
                    COSHead = new byte[5] { 0x80, 0x72, 0x00, 0x00, 0x04 };
                    Array.ConstrainedCopy(COSHead, 0, message.Body, 11, 5);
                    Array.ConstrainedCopy(LanePackage.LaneData, 22, message.Body, 16, message.Body.Length - 16);

                    if (Client.Send(message.ToBytes()) != message.ToBytes().Length)
                    {
                        if ((DateTime.Now - HistoryDate).TotalSeconds > TimeOut)
                        {
                            HistoryDate = DateTime.Now;
                            Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送校验MAC2包失败，数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                        }
                        Result = false;
                    }
                    else
                    {
                        HistoryDate = DateTime.Now;
                        Common.LogHelper.Info("PSAM加密盒子：" + Newtonsoft.Json.JsonConvert.SerializeObject(Entity) + "发送校验MAC2包成功，数据内容: " + Common.Check.ByteArrayToHexString(message.ToBytes()));
                    }
                    break;
                default:
                    break;

            }
            return Result;
        }
        #endregion

        #region 获取高低位
        public static short GetHighWord(short intval)
        {
            return (short)(intval >> 8);
        }

        public static short GetLowWord(short intval)
        {
            return (short)(intval << 8);
        }
        #endregion

    }
}
